package com.hmall.trade.listener;

import cn.hutool.core.util.ObjectUtil;
import com.hmall.trade.config.DelayMessagePostProcessor;
import com.hmall.trade.config.MutiDelayCheckMsg;
import com.hmall.trade.domain.po.Order;
import com.hmall.trade.service.IOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import static com.hmall.common.constants.MqConstants.*;
import static com.hmall.common.constats.MqConstants.*;
import static com.hmall.common.constats.MqConstants.*;
import static com.hmall.common.constats.MqConstants.PAY_EXCHANGE;
import static com.hmall.common.constats.MqConstants.PAY_SUCCESS_KEY;
import static com.hmall.common.constats.MqConstants.PAY_SUCCESS_QUEUE;

/**
 * @author Administrator
 * @version 1.0
 * @description: TODO
 * @date 2025/6/15 18:37
 * 是一个监听器主要用来监听支付成功消息
 */
@Slf4j
@Component
public class MqListener {
    @Autowired
    private IOrderService orderService;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name= PAY_SUCCESS_QUEUE,durable = "true"),
            exchange = @Exchange(name = PAY_EXCHANGE,type = ExchangeTypes.TOPIC),
            key = PAY_SUCCESS_KEY
    ))
    public void listenPaySuccessMsg(Long orderId){
        log.info("收到支付成功的消息，订单号：{}",orderId);
        // 1、做幂等性判断，如果订单状态是已支付，就不用修改订单状态
        Order order = orderService.getById(orderId);
        if(order == null || order.getStatus() != 1){
            return;
        }

        // 2、修改订单状态为已支付
        orderService.markOrderPaySuccess(orderId);

        // 幂等性判断优化写法
        // update order set status = 2,pay_time = now() where id = 1 and status = 1;
        /*boolean updateResult = orderService.lambdaUpdate()
                .eq(Order::getId, orderId)
                .eq(Order::getStatus, 1)
                .set(Order::getStatus, 2)
                .set(Order::getPayTime, LocalDateTime.now())
                .update();
        if(!updateResult){
            return;
        }*/
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = ORDER_DELAY_CHECK_QUEUE,durable = "true"),
            exchange = @Exchange(name = TRADE_ORDER_EXCHANGE,type = ExchangeTypes.TOPIC, delayed = "true"),
            key = ORDER_DELAY_CHECK_KEY
    ))
    public void listenerOrderDelayCheckMsg(MutiDelayCheckMsg<Long> msg){
        log.info("收到订单延迟检查的消息，订单消息：{}",msg);
        // 1、消息健壮性判断
        if(ObjectUtil.isNull(msg) || ObjectUtil.isNull(msg.getCoreMsgData())){
            return;
        }

        // 2、根据订单ID查询订单，判断订单状态是否为已支付，如果是，直接return
        Order order = orderService.getById(msg.getCoreMsgData());
        if(ObjectUtil.isNull(order) || order.getStatus() == 2){
            return;
        }

        // 3、如果还没有支付，检测是否还有下一个延时时间段，如果有，继续取时间发送延时消息
        if(msg.haveNextDelayTime()){
            rabbitTemplate.convertAndSend(TRADE_ORDER_EXCHANGE, ORDER_DELAY_CHECK_KEY, msg,
                    DelayMessagePostProcessor.of("delay",msg.removeAndGetNextDelayTime()));
            return;
        }

        // 4、如果没有延时时间了，取消订单（改订单状态为：已取消、释放库存）
        orderService.cacelOrder(msg.getCoreMsgData());
    }
}
